/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_IMAGEKNIFE_DISPATCHER_H
#define IMAGE_KNIFE_C_IMAGEKNIFE_DISPATCHER_H
#include <unordered_map>
#include <list>

#include "request/imageknife_request_internal.h"
#include "interceptor.h"
#include "queue/ijob_queue.h"
#include "queue/default_job_queue.h"
#include "imageknife_task_internal.h"
#include "imageknife_node_internal.h"

namespace ImageKnifePro {

class ImageKnifeDispatcher {
public:
    void Enqueue(std::shared_ptr<ImageKnifeRequestInternal> request);

    void CancelRequest(std::shared_ptr<ImageKnifeRequestInternal> request);

    std::shared_ptr<ImageData> LoadFromImageSourceSync(ImageSource *imageSource, Context context,
                                                       std::string memoryKey, std::string fileKey);

    void ProcessFrameModeDecoding(std::shared_ptr<ImageKnifeTaskInternal> task);
    int maxRequests = 8;

    static ImageKnifeDispatcher &GetInstance();
private:
    std::unordered_map<std::string, std::list<IJobQueue::Job>> executingJobMap_;
    IJobQueue *jobQueuePtr_ = new DefaultJobQueue();

    ImageKnifeDispatcher();
    ~ImageKnifeDispatcher();
    ImageKnifeDispatcher(const ImageKnifeDispatcher&) = delete;
    ImageKnifeDispatcher &operator = (const ImageKnifeDispatcher&) = delete;

    bool ExecuteJob(IJobQueue::Job);

    bool ExecuteTask(std::shared_ptr<ImageKnifeTaskInternal> task);

    bool LoadSrcFromMemory(IJobQueue::Job);

    // 图片源是本地pixelmap返回true，否则返回false
    bool LoadFromPixelmap(std::shared_ptr<ImageKnifeTaskInternal> task);

    IJobQueue::Job GenerateJob(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type);

    ImageSource *GetImageSrc(std::shared_ptr<ImageKnifeOption> option, ImageRequestType type);

    void LoadImageSource(std::shared_ptr<ImageKnifeTaskInternal> task);

    void LoadErrorSrc(std::shared_ptr<ImageKnifeRequestInternal> request);

    void OnComplete(std::shared_ptr<ImageKnifeTaskInternal> task);

    void CompleteExecutingList(const std::list<IJobQueue::Job> &executingList, const bool &canceled,
                               std::shared_ptr<ImageKnifeTaskInternal> task);

    bool ProcessImageDecodeTransform(std::shared_ptr<ImageKnifeTaskInternal> task);

    bool ProcessImageLoading(std::shared_ptr<ImageKnifeTaskInternal> task);

    void ProcessFileCache(std::shared_ptr<ImageKnifeTaskInternal> task);

    void ProcessCanceledRequest(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type,
                                std::string info, bool fromQueue = false);

    void ProcessSucceedRequest(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type,
                               std::shared_ptr<ImageKnifeTaskInternal> task);

    // 在js主线程执行失败的Request，不是task加载中产生的错误，则使用该函数
    void ProcessFailedRequest(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type,
                              std::string errorInfo);

    // 在加载过程中失败的【主图】Request使用该函数，会进行错误图加载
    void ProcessMainSrcFailedRequest(std::shared_ptr<ImageKnifeRequestInternal> request,
                                     std::shared_ptr<ImageKnifeTaskInternal> task);

    bool IsRequestOverdue(std::shared_ptr<ImageKnifeRequestInternal> request);

    bool ProduceImageCache(std::shared_ptr<ImageKnifeTaskInternal> task);

    bool DisplayImage(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type,
                      std::shared_ptr<ImageDataCache> imageData);

    // 为Image组件使用的base64字符串前面添加了上prefix： "data:image/xxx;base64," xxx为图片格式
    bool EncodeSourceBase64(std::shared_ptr<ImageKnifeTaskInternal> task);

    void TransformImage(std::shared_ptr<ImageKnifeTaskInternal> task);

    void DispatchNextJob();

    void CancelInterceptor(std::shared_ptr<ImageKnifeRequestInternal> request, ImageRequestType type);

    std::shared_ptr<ImageKnifeNodeInternal> GetImageKnifeNode(std::string id);
};

}

#endif // IMAGE_KNIFE_C_IMAGEKNIFE_DISPATCHER_H
